﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microhard.Permission.Interface;
using System.Web.Security;
using Microhard.Permission;
using Microhard.Permission.Models;
using System.Text;
using Microhard.Core.DBUtility;


namespace Microhard.Permission_MembershipImpl
{
    /// <summary>
    /// 功能权限实现
    /// </summary>
    public class PermissionImpl : IFuncAuthorization
    {

        #region IFuncAuthorization Members

        public bool IsApprove(Permission.Models.PermissionRequest request, out List<string> OperationKeyNames, out List<Microhard.Permission.Models.Permission> currentPermissions)
        {
            bool rtn = false;
            OperationKeyNames = null;
            currentPermissions = null;
            List<Microhard.Permission.Models.Permission> haspms = null;

            //从缓存中获取权限
            LongonUserPermissionCache lupc = new LongonUserPermissionCache();
            haspms = lupc.GetFromCache(request.UserName);
            if (haspms == null || haspms.Count == 0)
            {
                //获得用户拥有的功能权限
                MicrohardOUGDBDataContext db = new MicrohardOUGDBDataContext();
                var userEntity = db.aspnet_Users.SingleOrDefault(u => u.UserName == request.UserName);
                var dbhaspms = db.MicroHard_Permissions.Where(p => p.OwnerID == userEntity.UserId && p.OwnerType == (int)OwnerIDType.User).ToList();

                //获得用户所属角色拥有的权限
                var roleEntities = db.aspnet_UsersInRoles.Where(r => r.UserId == userEntity.UserId).Select(r => r.aspnet_Role).ToList();
                if (roleEntities != null)
                {
                    var rolehasPms = db.MicroHard_Permissions.Where(p => roleEntities.Select(r => r.RoleId).Contains(p.OwnerID) &&
                        p.OwnerType == (int)OwnerIDType.Role).ToList();
                    if (rolehasPms.Count > 0)
                    {
                        if (dbhaspms.Count > 0)
                        {
                            dbhaspms.AddRange(rolehasPms);
                        }
                        else
                        {
                            dbhaspms = rolehasPms;
                        }
                    }
                }
                haspms = dbhaspms.Select(x => x.ToModel()).ToList();
                lupc.UpdateCache(request.UserName, haspms);
            }

            if (haspms != null && haspms.Count > 0)
            {
                //验证是否拥有请求的权限（由于多个角色可以对同一个资源有多次功能授权，在这里全部取出来）
                var cnt = haspms.Where(p => p.ResourceKeyName.ToLower() == request.RequestResouce.KeyName.ToLower() &&
                    p.OperationKeyName.ToLower() == request.RequestOperation.KeyName.ToLower()).ToList();
                if (cnt != null && cnt.Count() > 0)
                {
                    rtn = true;
                    currentPermissions = cnt;
                    OperationKeyNames = haspms.Where(p => p.ResourceKeyName.ToLower() == request.RequestResouce.KeyName.ToLower()).Select(x => x.OperationKeyName.ToLower()).ToList();
                }
            }
            return rtn;
        }

        #endregion

        #region IRepository<Permission> Members

        public ExecutedResult Add(Permission.Models.Permission model)
        {
            ExecutedResult result = new ExecutedResult();
            MicrohardOUGDBDataContext db = new MicrohardOUGDBDataContext();
            List<MicroHard_Permission> toAddList = new List<MicroHard_Permission>();
            List<MicroHard_DataCollection> toAddScopeList = new List<MicroHard_DataCollection>();
            List<MicroHard_EntitiesInGroup> toAddGroups = new List<MicroHard_EntitiesInGroup>();
            List<MicroHard_DataCollectionScopeSpecific> toAddSpcScopes = new List<MicroHard_DataCollectionScopeSpecific>();

            foreach (var o in model.AssignOperations)
            {
                //添加功能权限
                var toAdd = new MicroHard_Permission();
                toAdd.PermissionID = Guid.NewGuid();
                toAdd.OwnerID = model.OwnerID;
                toAdd.ResID = model.ResID;
                toAdd.OperID = o.OperationID;
                toAdd.AssignDateTime = DateTime.Now;
                toAdd.OwnerType = model.OwnerType;
                toAddList.Add(toAdd);

                //添加数据权限
                MicroHard_DataCollection md = new MicroHard_DataCollection();
                md.DataCollectionID = Guid.NewGuid();
                md.PermissionID = toAdd.PermissionID;
                md.OwnerID = model.OwnerID;
                md.OwnerType = model.OwnerType;
                md.Scope = model.Scope;
                md.CreateTime = DateTime.Now;
                md.Name = model.ResourceName;
                toAddScopeList.Add(md);

                //特殊组权限
                if (model.Scope == (int)DataCollectionScope.Specific && model.SpecificScopes != null)
                {

                    foreach (var s in model.SpecificScopes)
                    {
                        toAddSpcScopes.Add(new MicroHard_DataCollectionScopeSpecific()
                        {
                            CreateTime = DateTime.Now,
                            CreatorID = model.OperatorID,
                            DataCollectionID = md.DataCollectionID,
                            EntityID = s.EntityID,
                            EntityType = (int)OwnerIDType.User,
                            Scope = model.Scope,
                            SpecificID = Guid.NewGuid()
                        });
                    }

                }
            }
            //功能权限
            db.MicroHard_Permissions.InsertAllOnSubmit(toAddList);
            //添加组
            var orgID = db.MicroHard_Resources.Single(r => r.ResourceID == model.ResID).MicroHard_Group.OrgID;
            var cnt = db.MicroHard_EntitiesInGroups.Count(m => m.EntityID == model.OwnerID && m.EntityType == model.OwnerType && m.OrgID == orgID);
            if (cnt == 0)
            {
                var addGroup = new MicroHard_EntitiesInGroup();
                addGroup.EntityID = model.OwnerID;
                addGroup.EntityType = model.OwnerType;
                addGroup.CreateTime = DateTime.Now;
                addGroup.OrgID = orgID;
                addGroup.OrgUserID = Guid.NewGuid();
                toAddGroups.Add(addGroup);
                //组范围
                db.MicroHard_EntitiesInGroups.InsertAllOnSubmit(toAddGroups);
            }
            //数据权限
            db.MicroHard_DataCollections.InsertAllOnSubmit(toAddScopeList);
            //组内特定范围功能权限
            db.MicroHard_DataCollectionScopeSpecifics.InsertAllOnSubmit(toAddSpcScopes);
            try
            {
                db.SubmitChanges();
                result.Scope.IsSysManage = true;
            }
            catch (Exception ex)
            {
                result.ErrorMsg.Add("PermissionImpl.Add", ex.Message);
            }
            return result;
        }

        public ExecutedResult Update(Permission.Models.Permission model)
        {
            throw new NotImplementedException();
        }

        public ExecutedResult Delete(List<Guid> ids)
        {
            throw new NotImplementedException();
        }

        public ExecutedResult Delete(Permission.Models.Permission model)
        {
            ExecutedResult result = new ExecutedResult();
            MicrohardOUGDBDataContext db = new MicrohardOUGDBDataContext();
            var toDeltes = from b in db.MicroHard_Permissions
                           where b.OwnerID == model.OwnerID && b.ResID == model.ResID
                           select b;
            var scopeToDel = from p in db.MicroHard_DataCollections
                             where toDeltes.Select(j => j.PermissionID).Contains(p.PermissionID)
                             select p;
            var spcScopeDels = from s in scopeToDel
                               from sp in db.MicroHard_DataCollectionScopeSpecifics
                               where s.Scope == (int)DataCollectionScope.Specific
                               && s.DataCollectionID == sp.DataCollectionID
                               select sp;
            //删除特殊组权限
            db.MicroHard_DataCollectionScopeSpecifics.DeleteAllOnSubmit(spcScopeDels);
            //删除数据权限
            db.MicroHard_DataCollections.DeleteAllOnSubmit(scopeToDel);
            //删除功能权限
            db.MicroHard_Permissions.DeleteAllOnSubmit(toDeltes);

            try
            {
                db.SubmitChanges();
                scope.PKID = new List<Guid>();
                //准备删除的数据项
                scope.PKID.AddRange(scopeToDel.Select(s => s.DataCollectionID).ToList());
                scope.PKID.AddRange(toDeltes.Select(p => p.PermissionID).ToList());
            }
            catch (Exception ex)
            {
                result.ErrorMsg.Add("PermissionImpl.Delete", ex.Message);
            }
            return result;
        }

        public Permission.Models.Permission GetModelByID(Guid id)
        {
            MicrohardOUGDBDataContext db = new MicrohardOUGDBDataContext();
            var entity = db.MicroHard_Permissions.SingleOrDefault(b => b.PermissionID == id);
            if (entity != null)
                return entity.ToModel();
            return null;
        }


        public Permission.Models.Permission GetModelByModel(Permission.Models.Permission model)
        {
            throw new NotImplementedException();
        }

        public class PermissionCamper : IEqualityComparer<MicroHard_Permission>
        {

            #region IEqualityComparer<MicroHard_Permission> Members

            public bool Equals(MicroHard_Permission x, MicroHard_Permission y)
            {
                if (x == null)
                    return false;
                if (y == null)
                    return false;
                if (x.OwnerID != y.OwnerID)
                    return false;
                if (x.ResID != y.ResID)
                    return false;
                return true;
            }

            public int GetHashCode(MicroHard_Permission obj)
            {
                return obj.OwnerID.GetHashCode();
            }

            #endregion
        }

        public List<Permission.Models.Permission> Query(Permission.Models.Permission Model, int pageIndex, int pageSize, out int totalCount)
        {
            List<Permission.Models.Permission> result = new List<Permission.Models.Permission>();
            MicrohardOUGDBDataContext db = new MicrohardOUGDBDataContext();
            //按照Owner,资源进行过滤
            //TODO后期改造为视图或存储过程
            IEnumerable<MicroHard_Permission> singlePermission = null;
            //按照用户查询
            if (Model.OwnerType == (int)OwnerIDType.User)
            {
                singlePermission = db.MicroHard_Permissions.Where(p => p.OwnerType == Model.OwnerType).ToList().Distinct(new PermissionCamper());
            }
            else
            {
                //按照角色查询
                singlePermission = db.MicroHard_Permissions.Where(p => p.OwnerID == Model.OwnerID && p.OwnerType == Model.OwnerType).ToList().Distinct(new PermissionCamper());
            }
            totalCount = singlePermission.Count();
            var pagedEntities = singlePermission.OrderBy(u => u.OwnerID).ToList().Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList();

            foreach (var s in pagedEntities)
            {
                var hasOperations = db.MicroHard_Permissions.Where(p => p.OwnerID == s.OwnerID && p.ResID == s.ResID);
                Permission.Models.Permission tmpPis = new Permission.Models.Permission();
                tmpPis.AssignDateTime = s.AssignDateTime;
                tmpPis.AssignOperations = hasOperations.OrderBy(p => p.OperID).Select(o => o.MicroHard_Operation.ToModel()).ToList();
                tmpPis.OwnerID = s.OwnerID;
                tmpPis.OwnerType = s.OwnerType;
                if (tmpPis.OwnerType == (int)OwnerIDType.User)
                {
                    var user = db.aspnet_Users.SingleOrDefault(u => u.UserId == s.OwnerID);
                    if (user != null)
                    {
                        tmpPis.OwnerName = user.UserName;
                    }
                }
                else
                {
                    var role = db.aspnet_Roles.SingleOrDefault(u => u.RoleId == s.OwnerID);
                    if (role != null)
                    {
                        tmpPis.OwnerName = role.RoleName;
                    }
                }
                tmpPis.ResID = s.ResID;
                tmpPis.ResourceName = s.MicroHard_Resource.Name;
                tmpPis.BelongGroup = s.MicroHard_Resource.MicroHard_Group.OrgName;
                var dcp = (from dc in db.MicroHard_DataCollections
                           from p in hasOperations
                           where p.PermissionID == dc.PermissionID
                           select dc.Scope).ToList().Distinct();
                StringBuilder sb = new StringBuilder();
                foreach (var d in dcp)
                {
                    var dcsEnum = (DataCollectionScope)Enum.Parse(typeof(DataCollectionScope), d.ToString());
                    switch (dcsEnum)
                    {
                        case DataCollectionScope.All: sb.Append("所有,"); break;
                        case DataCollectionScope.Group: sb.Append("所在组,"); break;
                        case DataCollectionScope.Self: sb.Append("仅自己,"); break;
                        case DataCollectionScope.None: sb.Append("无,"); break;
                        case DataCollectionScope.Specific: sb.Append("特殊,"); break;
                        case DataCollectionScope.Custome: sb.Append("自定义"); break;
                    }
                }
                tmpPis.ScopeDisplyName = sb.ToString();
                result.Add(tmpPis);
            }
            return result;
        }

        public List<Permission.Models.Permission> Query(Permission.Models.Permission Model)
        {
            throw new NotImplementedException();
        }

        #endregion


        #region IFuncAuthorization Members


        public List<Telerik.Web.Mvc.UI.MenuItem> GetMenusByPermission(string userName)
        {
            List<Telerik.Web.Mvc.UI.MenuItem> rtn = new List<Telerik.Web.Mvc.UI.MenuItem>();
            if (string.IsNullOrEmpty(userName))
                return rtn;
            MicrohardOUGDBDataContext db = new MicrohardOUGDBDataContext();
            //TODO后期改造为视图或存储过程
            //通过User获得权限
            var user = db.aspnet_Users.SingleOrDefault(u => u.LoweredUserName == userName.ToLower());
            var userId = Guid.Empty;
            if (user != null)
            {
                userId = user.UserId;
            }
            if (userId == Guid.Empty)
                return rtn;
            List<MicroHard_Permission> singlePermission = db.MicroHard_Permissions.ToList().Distinct(new PermissionCamper()).Where(u => u.OwnerID == userId).ToList();
            //通过role获得权限
            var roles = db.aspnet_UsersInRoles.Where(u => u.UserId == userId).Select(r => r.aspnet_Role).ToList();
            if (roles != null)
            {
                var rolePerms = db.MicroHard_Permissions.ToList().Distinct(new PermissionCamper()).Where(u => roles.Select(r => r.RoleId).Contains(u.OwnerID)).ToList();
                if (singlePermission == null)
                {
                    singlePermission = new List<MicroHard_Permission>();
                }
                if (rolePerms != null)
                {
                    foreach (var rp in rolePerms)
                    {
                        if (!singlePermission.Contains(rp, new PermissionComparer()))
                        {
                            singlePermission.Add(rp);
                        }
                    }
                }
            }
            //获得resource type
            Dictionary<string, Telerik.Web.Mvc.UI.MenuItem> dicMenus = new Dictionary<string, Telerik.Web.Mvc.UI.MenuItem>();
            var resType = db.MicroHard_ResourceTypes.ToList();
            foreach (var type in resType)
            {

                foreach (var res in singlePermission.Where(d => d.MicroHard_Resource.ResourceTypeID == type.ResourceTypeID && d.MicroHard_Resource.ShowOnMenu.Value == true).OrderBy(c => c.ResID))
                {
                    string resTypeName = res.MicroHard_Resource.MicroHard_ResourceType.Name;
                    Telerik.Web.Mvc.UI.MenuItem mainItem = null;

                    Telerik.Web.Mvc.UI.MenuItem subItem = new Telerik.Web.Mvc.UI.MenuItem();
                    subItem.Text = res.MicroHard_Resource.Name;
                    //subItem.ActionName = "Index";
                    //subItem.ControllerName = res.MicroHard_Resource.KeyName;
                    if (!string.IsNullOrEmpty(type.KeyName))
                    {
                        //注意area的名称必须和项目中area的名称一样，包括大小写。不然telerik menu会不识别，抛出null exception
                        //subItem.RouteValues.Add("area", type.KeyName);
                        subItem.Url = "~/" + type.KeyName + "/" + res.MicroHard_Resource.KeyName + "/Index";
                    }


                    if (dicMenus.ContainsKey(resTypeName))
                    {
                        mainItem = dicMenus[resTypeName];
                        mainItem.Items.Add(subItem);
                    }
                    else
                    {
                        mainItem = new Telerik.Web.Mvc.UI.MenuItem();
                        mainItem.Text = resTypeName;
                        mainItem.Items.Add(subItem);
                        dicMenus.Add(resTypeName, mainItem);
                    }
                }
            }

            //组装
            foreach (var m in dicMenus.OrderBy(d => d.Key))
            {
                rtn.Add(m.Value);
            }
            return rtn.ToList();
        }

        #endregion

        #region IFuncAuthorization Members


        public bool IsDuplicate(Permission.Models.Permission model)
        {
            if (model.AssignOperations == null)
                return false;
            if (model.ResID == Guid.Empty)
                return false;
            MicrohardOUGDBDataContext db = new MicrohardOUGDBDataContext();
            var opers = (from p in db.MicroHard_Permissions
                         where p.OwnerID == model.OwnerID && p.ResID == model.ResID
                         && p.OwnerType == model.OwnerType
                         select p).ToList();
            int count = (from hasOper in opers
                         from o in model.AssignOperations
                         where o.OperationID == hasOper.OperID
                         select hasOper).Count();
            if (count > 0)
                return true;
            return false;
        }

        #endregion

        #region IRepository<Permission> Members


        public ScopeResult scope
        {
            get;
            set;
        }

        #endregion
    }
}
